/*
 * Created on 2005-2-25
 *
 */
package bma.common.langutil.core;

import java.io.PrintWriter;
import java.io.StringWriter;

/**
 * 异常工具类
 * 
 * @author 关中
 * @since 1.0 (imported from BMA.ESP Project)
 * 
 */
public class ExceptionUtil {

	public static RuntimeException throwRuntime(Throwable e) {
		if (e instanceof RuntimeException) {
			return (RuntimeException) e;
		}
		if (e instanceof Error) {
			Error err = (Error) e;
			throw err;
		}
		return new IgnoredException(e);
	}

	public static Throwable unwrap(Throwable e) {
		if (e instanceof IgnoredException) {
			IgnoredException w = (IgnoredException) e;
			return unwrap(w.getCause());
		}
		return e;
	}

	public static Throwable cause(Throwable e) {
		Throwable l = e;
		Throwable t = l.getCause();
		while (t != null) {
			l = t;
			t = l.getCause();
		}
		return l;
	}

	public static String toStackTraceString(Throwable ex) {
		if (ex == null) {
			return null;
		}
		StringWriter sw = new StringWriter();
		PrintWriter ps = new PrintWriter(sw);
		ex.printStackTrace(ps);
		return sw.toString();
	}

	public static String writeStackTraceElementToString(StackTraceElement e,
			char sp) {
		if (sp == 0)
			sp = '\t';
		StringBuilder r = new StringBuilder();
		r.append(ValueUtil.stringValue(e.getClassName(), "")).append(sp)
				.append(ValueUtil.stringValue(e.getMethodName(), ""))
				.append(sp).append(ValueUtil.stringValue(e.getFileName(), ""))
				.append(sp).append(e.getLineNumber());
		return r.toString();
	}

	public static StackTraceElement readStackTraceElementFromString(String s,
			char sp) {
		String[] slist = StringUtil.tokenSplit(s, sp + "");
		String declaringClass = slist[0];
		String methodName = null;
		if (slist.length > 1) {
			methodName = ValueUtil.stringValue(slist[1], null);
		}
		String fileName = null;
		if (slist.length > 2) {
			fileName = ValueUtil.stringValue(slist[2], null);
		}
		int lineNumber = -1;
		if (slist.length > 3) {
			lineNumber = ValueUtil.intValue(slist[3], -1);
		}
		return new StackTraceElement(declaringClass, methodName, fileName,
				lineNumber);
	}

	public static <TYPE extends Throwable> TYPE mergeException(TYPE error,
			StackTraceElement hr, Throwable cur, int currentStackLimit) {
		StackTraceElement[] elist = mergeStackTraces(error.getStackTrace(), hr,
				cur.getStackTrace(), currentStackLimit);
		error.setStackTrace(elist);
		return error;
	}

	public static StackTraceElement[] mergeStackTraces(
			StackTraceElement[] oldStack, StackTraceElement hr,
			StackTraceElement[] currentStack, int currentStackLimit) {

		int clen = Math.min(currentStack.length, currentStackLimit);
		int hrp = (hr == null ? 0 : 1);

		StackTraceElement[] zusammen = new StackTraceElement[clen
				+ oldStack.length + hrp];
		System.arraycopy(oldStack, 0, zusammen, 0, oldStack.length);
		if (hr != null) {
			zusammen[oldStack.length] = hr;
		}
		System.arraycopy(currentStack, 0, zusammen, oldStack.length + hrp, clen);
		return zusammen;
	}

}
